﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
using System.Configuration;

namespace MobiShop.Models
{
    public class ShoppingBasketException : Exception
    {
        private int _errorID;
        public int ErrorID
        {
            get { return _errorID; }
        }

        public ShoppingBasketException(int ErrorID, string message)
            : base(message)
        {
            this._errorID = ErrorID;
        }
    }

    public class ShoppingBasket
    {
        #region "thuộc tính"
        private Hashtable _listProduct = new Hashtable();
        private int _totalQuantity = 0;

        public int Count
        {
            get { return _listProduct.Count; }
        }

        public int TotalQuantity
        {
            get { return _totalQuantity; }
        }

        public Hashtable ListProduct
        {
            get { return _listProduct; }
        }

        public List<int> ListProduct_ID
        {
            get{ return _listProduct.Keys.OfType<int>().ToList(); }
        }

        private decimal _sumPrice=0;
        // SumPrice sẽ không tự động được tính lại mỗi khi giỏ hàng có sự thay đổi
        // => phải chắc chắn rằng đã gọi hàm CalculatorSumPrice để tính toán lại tổng giá trị
        // nếu trước đó có sự thay đổi trong giỏ hàng
        public decimal TotalPrice
        {
            get { return _sumPrice; }
        }

        public static readonly int maxOfEachProductQuantity = int.Parse(ConfigurationManager.AppSettings["maxOfEachProductQuantity"]);
        public static readonly int maxOfTotalProductsQuantity = int.Parse(ConfigurationManager.AppSettings["maxOfTotalProductsQuantity"]);
        public static readonly bool useCreditCard = bool.Parse(ConfigurationManager.AppSettings["useCreditCard"]);
        #endregion

        #region "Phương thức"
        // Mã ngoại lệ trả về :
        // 0 : ok
        // 1 : mã hàng id ko tồn tại
        // 2 : Ko đủ hàng cung ứng
        // 3 : Yêu cầu đặt hàng vượt quá giới hạn số lượng tối đa của 1 loại sản phẩm,
        // bao gồm cả trường hợp quantity âm
        // 4 : Tổng số sản phẩm đặt hàng vượt quá số lượng cho phép của 1 hóa đơn bán lẻ online
        // 5 : Mặt hàng chưa có giá ( == null ), ko thể đặt hàng
        public void UpdateQuantity(int id, int quantity, bool AddIfExists = false)
        {
            Product product = ProductModels.GetProductById(id);
            if (product == null)
            {
                RemoveProduct(id); 
                throw new ShoppingBasketException(1, "");
            }
            if (product.price == null)
            {
                RemoveProduct(id);
                throw new ShoppingBasketException(5, product.name);
            }

            int newTotal;
            if (_listProduct.ContainsKey(id))
            {
                if (AddIfExists)
                {
                    newTotal = _totalQuantity + quantity;
                    quantity += (int)_listProduct[id];
                }
                else
                {
                    newTotal = _totalQuantity - (int)_listProduct[id] + quantity;
                }
            }
            else
            {
                newTotal = _totalQuantity + quantity;
            }

            if (quantity < 0 || quantity > maxOfEachProductQuantity) throw new ShoppingBasketException(3, product.name);
            if (newTotal > maxOfTotalProductsQuantity) throw new ShoppingBasketException(4, product.name);
            if (product.totalQuantity < quantity) throw new ShoppingBasketException(2, product.name);

            _listProduct[id] = quantity;
            _totalQuantity = newTotal;
        }

        public void RemoveProduct(int id)
        {
            if (_listProduct.ContainsKey(id))
            {
                _totalQuantity -= (int)_listProduct[id];
                _listProduct.Remove(id);
            }
        }

        public int? GetQuantity(int id)
        {
            return (int?)_listProduct[id];
        }

        public List<Product> GetProductList()
        {
            return ProductModels.GetProductsFromListID(ListProduct_ID);
        }

        public void CalculatorSumPrice()
        {
            _sumPrice = 0;
            List<Product> list = ProductModels.GetProductsFromListID(ListProduct_ID);
            foreach (Product product in list)
            {
                _sumPrice += (decimal)product.price * (int)_listProduct[product.id];            
            }
        }

        public void Clear()
        {
            _listProduct = new Hashtable();
            _totalQuantity = 0;
            _sumPrice = 0;
        }
        #endregion
    }
}